/*
 * Copyright (C) ${year} Jeffrey Palm.
 *
 * This code is part of the Floto Project (http://jeffpalm.com/floto/).
 * Please consult the LICENSE included in the distribution.
 */
package com.jeffpalm.floto.isight.osx;

import java.awt.Component;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferInt;
import java.awt.image.DirectColorModel;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;

import javax.swing.JFrame;

import quicktime.QTSession;
import quicktime.qd.Pict;
import quicktime.qd.QDConstants;
import quicktime.qd.QDGraphics;
import quicktime.qd.QDRect;
import quicktime.std.sg.SequenceGrabber;

import com.jeffpalm.floto.isight.AbstractCapture;
import com.jeffpalm.floto.isight.Capture;

/**
 * Takes a snap shot using quicktime.
 * 
 * TODO: Convert to reflection.
 */
public final class QuicktimeCapture extends AbstractCapture.Webcam {

  /*
   * (non-Javadoc)
   * 
   * @see Capture#takeSnapshot()
   */
  public Snapshot takeSnapshot() throws Exception {

    QTSession.open();

    // Configure the camera
    QDRect cameraImageSize = new QDRect(640, 480);
    QDGraphics gWorld;
    if (quicktime.util.EndianOrder.isNativeLittleEndian()) {
      gWorld = new QDGraphics(QDConstants.k32BGRAPixelFormat, cameraImageSize);
    } else {
      gWorld = new QDGraphics(QDGraphics.kDefaultPixelFormat, cameraImageSize);
    }
    SequenceGrabber sg = new SequenceGrabber();
    sg.setGWorld(gWorld, null);

    // Grab the picture
    Pict.fromSequenceGrabber(sg, cameraImageSize, 0, 0);

    // If you are happy with a Quicktime Pict object - thats all. You might save
    // it
    // to disk for example using the pict.writeToFile()-Method

    // If you want to have a BufferedImage, there is some work left:
    int size = gWorld.getPixMap().getPixelData().getSize();
    int intsPerRow = gWorld.getPixMap().getPixelData().getRowBytes() / 4;
    size = intsPerRow * cameraImageSize.getHeight();
    final int[] pixelData = new int[size];
    DataBuffer db = new DataBufferInt(pixelData, size);
    ColorModel colorModel = new DirectColorModel(32, 0x00ff0000, 0x0000ff00, 0x000000ff);
    int[] masks = { 0x00ff0000, 0x0000ff00, 0x000000ff };
    WritableRaster raster = Raster.createPackedRaster(db, cameraImageSize.getWidth(), cameraImageSize.getHeight(),
        intsPerRow, masks, null);
    final BufferedImage image = new BufferedImage(colorModel, raster, false, null);

    // Copy Picture data to the raw image
    gWorld.getPixMap().getPixelData().copyToArray(0, pixelData, 0, pixelData.length);

    return newSnapshot(image, cameraImageSize.getWidth(), cameraImageSize.getHeight());
  }

  public static void main(String args[]) {
    try {
      final Capture.Snapshot data = new QuicktimeCapture().takeSnapshot();
      final BufferedImage image = data.getImage();
      final int width = data.getWidth();
      final int height = data.getHeight();

      // Fine - now we want to see the picture:
      JFrame myFrame = new JFrame("Snapshot");
      myFrame.add(new Component() {
        private static final long serialVersionUID = 1L;

        public void paint(Graphics g) {
          super.paint(g);
          g.drawImage(image, 0, 0, this);
        };
      });
      myFrame.setBounds(100, 100, width, height);
      myFrame.pack();
      myFrame.setVisible(true);

    } catch (Exception ex) {
      System.err.println("Got Exception:");
      ex.printStackTrace();
    }

    QTSession.close();
  }
}